----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    10:40:20 11/22/2011 
-- Design Name: 
-- Module Name:    dac_controller - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity dac_controller is
    generic(n : natural:=16);
port(   clk   : in  	STD_LOGIC;
		  DIN	  : in 	STD_LOGIC_VECTOR(15 downto 0);
		  PC_WE : in 	STD_LOGIC_VECTOR(15 downto 0);
		  res   : in   STD_LOGIC_VECTOR(15 downto 0);
		  LED   : out 	STD_LOGIC_VECTOR(15 downto 0);
		  DOUT  : out  STD_LOGIC;
		  SCLK  : out  STD_LOGIC;
		  SYNC  : out 	STD_LOGIC);
end dac_controller;

architecture Behavioral of dac_controller is

--component counter is                  --frequency divider, SCLK cycle time of DAC is 33ns. The counter 
                                      --divide the frequency into 2^n times, here is 3*2^4 = 48 ns
--generic(n:natural := 4);
--    port ( clk : in  STD_LOGIC;
--			  reset : in STD_LOGIC;
--           dout : out  STD_LOGIC);
--end component;

--state machine of the dac_controller--
  type state_type is (IDLE, ENABLE); -- with ENABLE mode
  signal state, next_state : state_type;
  --signal port_sel: std_logic_vector (1 downto 0);
--   signal ifetch : memory_in := (adr => (others => '0' ), we => '0', enable => '0', data => (others => '0' ));
  signal counter : std_logic_vector(3 downto 0) := (others => '1');
  signal sync_out : std_logic := '1';
  signal reg, temp : std_logic_vector(n-1 downto 0);
  
--  signal dac_reset : std_logic;
  signal nclk : std_logic:='1';
  signal clk_count : std_logic_vector(3 downto 0) := (others =>'0');
  signal flag : std_logic:='0';
  signal done : std_logic:='0';
begin

--   freq_div : counter port map(clk=>clk,reset=>dac_reset,dout=>nclk);
  
  
    SYNC <= sync_out;
    DOUT <= reg(n-1);
    SCLK <= nclk;
	 
	 process(res, clk)
	 begin
			if (res(0) = '1') then
				clk_count <= "0000";
				nclk <= '1';
			elsif (clk'event and clk='1') then
				if (unsigned(clk_count) = (n-1)) then -- 0 to (n/2-1) = n clocks here is 16
					nclk <= NOT(nclk);
					clk_count <= "0000";
				else
					clk_count <= std_logic_vector(unsigned(clk_count)+1);
				end if;
			end if;
	 end process;

	 
    process( nclk, res)                 -- sequential process of FSM
    begin
    	 
	   if(res(0) ='1') then             -- synchronus reset
          state <= IDLE;       -- starts with the IDLE stat
		else
			if rising_edge(nclk) then -- rising clock edge
       
		 case state is

        when IDLE =>
            done <='0';
            if (flag = '1' and PC_WE(0) = '0') then            
                 state <= ENABLE;
  					  counter <= std_logic_vector(unsigned(counter)+1);					  
            else
                 state <= IDLE;
					  sync_out <= '1';
            end if;
             
        when ENABLE =>         
            if (counter = "1111") then   -- all the data bits are sent 
					  
					  done <= '1';          
					  state <= IDLE; 
                 					  
            else 
            if (counter = "0000") then
               reg <= temp; 
            else 
               reg <= reg(n-2 downto 0) & '0';
            end if;					  
					  state <= ENABLE;
					  counter <= std_logic_vector(unsigned(counter)+1);
					  sync_out <= '0';
            end if;
				
      end case;    

		end if;
	 end if;
    end process;
         
    process(clk, PC_WE, DIN, done)      
    begin
   
      if (clk'event and clk='1') then
          if PC_WE(0) = '1' then
            flag <= '1';
            temp <= DIN;
          elsif flag = '1' then
            if (done = '1') then
            flag <= '0';
            temp <= x"0000";
            end if;
          else temp <= x"0000";
          end if;
        end if;
        end process;
        
--      if (clk'event and clk='1') then
--        if (flag = '0') then
--          if PC_WE(0) = '1' then
--           flag <= '1';
--          end if;
--          temp <= x"0000";
--        else
--          if PC_WE(0) = '1' then
--          temp <= DIN;
--          end if;
--          if (done = '1') then
--            flag <= '0';
--          end if;
--        end if;
--      end if; 
--    end process;
    

end Behavioral;

